<script setup>
import { useNodeTreeStore } from 'src/stores/nodeTree';
import { inject, defineExpose, computed } from 'vue';
import { computedRotateLayout } from 'src/pages/BiographicalNotes/common/utils';
defineOptions({
  name: 'ShapeCom',
});
defineProps({
  active: {
    type: Boolean,
    default: false,
  },
  'allow-rotation': {
    default: true,
    type: Boolean,
  },
});
const emit = defineEmits(['before-move', 'after-move', 'mousedown']);
const nodeTreeStore = useNodeTreeStore();
const pageWidth = inject('pageWidth');
const pageHeight = inject('pageHeight');
const layout = computed({
  get() {
    return (
      nodeTreeStore.activeNode?.layout || {
        x: 0,
        y: 0,
        width: 0,
        height: 0,
        rotate: 0,
        zIndex: 1,
      }
    );
  },
  set(val) {
    nodeTreeStore.activeNode.layout = val;
  },
});
const node = computed({
  get() {
    return nodeTreeStore.activeNode;
  },
  set(val) {
    nodeTreeStore.activeNode = val;
  },
});
const resizeMove = {
  'n-resize': (e, layout, start) => {
    const deltaY = e.clientY - start.y;
    if (start.layoutY + deltaY < 0) {
      layout.y = 0;
      layout.height = start.height + start.layoutY;
    } else if (start.height - deltaY < 0) {
      layout.y = start.layoutY + start.height;
      layout.height = 0;
    } else {
      layout.y = start.layoutY + deltaY;
      layout.height = start.height - deltaY;
    }
    return layout;
  },

  'e-resize': (e, layout, start) => {
    const delta = Number(e.clientX) - start.x;
    if (start.width + delta < 0) {
      layout.width = 0;
    } else if (start.layoutX + start.width + delta > pageWidth.value) {
      layout.width = pageWidth.value - start.layoutX;
    } else {
      layout.width = start.width + delta;
    }

    return layout;
  },
  'w-resize': (e, layout, start) => {
    const delta = e.clientX - start.x;
    if (nodeTreeStore.noScope) {
      layout.width = start.width - delta;
      layout.x = start.layoutX + delta;
    } else if (start.width - delta < 0) {
      layout.width = 0;
      layout.x = start.layoutX + start.width;
    } else if (start.layoutX - delta < 0) {
      layout.width = start.layoutX + start.width;
      layout.x = 0;
    } else {
      layout.width = start.width - delta;
      layout.x = start.layoutX + delta;
    }
    return layout;
  },
  's-resize': (e, layout, start) => {
    const delta = e.clientY - start.y;
    if (start.height + delta < 0) {
      layout.height = 0;
    } else if (start.layoutY + start.height + delta > pageHeight.value) {
      layout.height = pageHeight.value - start.layoutY;
    } else {
      layout.height = start.height + delta;
    }

    return layout;
  },
  'ne-resize': (e, layout, start) => {
    const deltaX = Number(e.clientX) - start.x;
    const deltaY = Number(e.clientY) - start.y;
    if (start.layoutY + deltaY < 0) {
      layout.y = 0;
      layout.height = start.height + start.layoutY;
    } else if (start.height - deltaY < 0) {
      layout.y = start.layoutY + start.height;
      layout.height = 0;
    } else {
      layout.y = start.layoutY + deltaY;
      layout.height = start.height - deltaY;
    }
    if (start.width + deltaX < 0) {
      layout.width = 0;
    } else if (start.layoutX + start.width + deltaX > pageWidth.value) {
      layout.width = pageWidth.value - start.layoutX;
    } else {
      layout.width = start.width + deltaX;
    }
    return layout;
  },
  'se-resize': (e, layout, start) => {
    const deltaX = Number(e.clientX) - start.x;
    const deltaY = Number(e.clientY) - start.y;
    layout.width = start.width + deltaX;
    layout.height = start.height + deltaY;
    if (layout.width <= 0) {
      layout.width = 0;
    }
    if (layout.height <= 0) {
      layout.height = 0;
    }
    return layout;
  },

  'sw-resize': (e, layout, start) => {
    const deltaX = start.x - Number(e.clientX);
    const deltaY = start.y - Number(e.clientY);
    layout.width = start.width + deltaX;
    layout.height = start.height - deltaY;
    layout.x = start.layoutX - deltaX;
    if (layout.width < 0) {
      layout.width = 0;
      layout.x = start.layoutX + start.width;
    }
    if (layout.height < 0) {
      layout.height = 0;
    }
    return layout;
  },

  'nw-resize': (e, layout, start) => {
    const deltaX = start.x - Number(e.clientX);
    const deltaY = start.y - Number(e.clientY);
    layout.width = start.width + deltaX;
    layout.height = start.height + deltaY;
    layout.x = start.layoutX - deltaX;
    layout.y = start.layoutY - deltaY;
    if (layout.height < 0) {
      layout.height = 0;
      layout.y = start.layoutY + start.height;
    }
    if (layout.width < 0) {
      layout.width = 0;
      layout.x = start.layoutX + start.width;
    }
    return layout;
  },
  move: (e, layout, start) => {
    const moveX = Number(e.clientX) - start.x;
    const moveY = Number(e.clientY) - start.y;
    const resultX = start.layoutX + moveX;
    const resultY = start.layoutY + moveY;
    // if (nodeTreeStore.noScope) return layout;
    if (nodeTreeStore.noScope) {
      layout.x = resultX;
      layout.y = resultY;
    } else {
      if (resultX < 0) {
        layout.x = 0;
      } else if (resultX + layout.width > pageWidth.value) {
        layout.x = pageWidth.value - layout.width;
      } else {
        layout.x = resultX;
      }
      if (resultY < 0) {
        layout.y = 0;
      } else if (resultY + layout.height > pageHeight.value) {
        layout.y = pageHeight.value - layout.height;
      } else {
        layout.y = resultY;
      }
    }
    return layout;
  },
  rotate: (e, layout, start) => {
    const moveX = Number(e.clientX) - start.radiusX;
    const moveY = Number(e.clientY) - start.radiusY;
    const angle = Math.atan2(moveY, moveX) * (180 / Math.PI);
    // 限制角度在 0 到 360 度之间
    layout.rotate = Math.round(((angle % 360) + 360) % 360);
    return computedRotateLayout(layout);
  },
};
const resizes = [
  {
    direction: 'n-resize',
    style: {
      left: '50%',
      top: 0,
      transform: 'translate(-50%, -50%)',
      cursor: 'n-resize',
    },
  },
  {
    direction: 's-resize',
    style: {
      left: '50%',
      bottom: 0,
      transform: 'translate(-50%, 50%)',
      cursor: 's-resize',
    },
  },
  {
    direction: 'e-resize',
    style: {
      right: 0,
      top: '50%',
      transform: 'translate(50%, -50%)',
      cursor: 'e-resize',
    },
  },
  {
    direction: 'w-resize',
    style: {
      left: 0,
      top: '50%',
      transform: 'translate(-50%, -50%)',
      cursor: 'w-resize',
    },
  },
  {
    direction: 'ne-resize',
    style: {
      right: 0,
      top: 0,
      transform: 'translate(50%, -50%)',
      cursor: 'ne-resize',
    },
  },
  {
    direction: 'nw-resize',
    style: {
      left: 0,
      top: 0,
      transform: 'translate(-50%, -50%)',
      cursor: 'nw-resize',
    },
  },
  {
    direction: 'se-resize',
    style: {
      right: 0,
      bottom: 0,
      transform: 'translate(50%, 50%)',
      cursor: 'se-resize',
    },
  },
  {
    direction: 'sw-resize',
    style: {
      left: 0,
      bottom: 0,
      transform: 'translate(-50%, 50%)',
      cursor: 'sw-resize',
    },
  },
];
const mousedown = (e, direction) => {
  if (node.value.lock) return;
  e.preventDefault();
  e.stopPropagation();
  nodeTreeStore.setMoveStatus(true, direction);
  nodeTreeStore.recordSnapshot();
  console.log(layout.value);
  const start = {
    x: Number(e.clientX),
    y: Number(e.clientY),
    layoutX: layout.value.x,
    layoutY: layout.value.y,
    width: layout.value.width,
    height: layout.value.height,
    rotate: layout.value.rotate, // 旋转角度
    radiusX: Number(e.clientX),
    radiusY: Number(e.clientY),
    centerX: layout.value.x + layout.value.width / 2,
    centerY: layout.value.y + layout.value.height / 2,
  };
  let fist = true;
  emit('before-move', e, direction);
  const move = (e) => {
    if (fist) {
      fist = false;
      return;
    }
    // layout.value.moveEvent = e;
    layout.value = resizeMove[direction](e, { ...layout.value }, start);
  };
  const up = () => {
    document.removeEventListener('mousemove', move);
    document.removeEventListener('mouseup', up);
    nodeTreeStore.setMoveStatus(false);
  };
  document.addEventListener('mousemove', move);
  document.addEventListener('mouseup', up);
};
const lockChange = () => {
  let lock = !node.value.lock;
  // if (node.value.lock) return;
  const recursive = (node) => {
    node.lock = lock;
    if (node.children) {
      node.children.forEach((item) => {
        recursive(item);
      });
    }
  };
  recursive(node.value);
};
nodeTreeStore.setHandleActive((event) => {
  mousedown(event, 'move');
});
defineExpose({
  mousedown,
});
</script>
<template>
  <div
    @mousedown="mousedown($event, 'move')"
    :class="{
      node: true,
      active_node: true,
      'lock-node': node.lock,
    }"
    :style="{
      width: layout.width + 'px',
      height: layout.height + 'px',
      transform: `translate(${layout.x}px, ${layout.y}px) rotate(${layout.rotate || 0}deg)`,
      zIndex: node.lock ? layout.zIndex - 1 : layout.zIndex + 1,
    }"
  >
    <template v-if="!node.lock">
      <div
        v-for="res in resizes"
        :key="res"
        :style="res.style"
        :class="res.direction"
        @mousedown="mousedown($event, res.direction)"
      ></div>
    </template>
    <template v-if="!node.lock">
      <q-icon
        name="redo"
        v-if="allowRotation"
        class="rotate text-primary"
        @mousedown="mousedown($event, 'rotate')"
      ></q-icon>
    </template>
    <q-icon
      v-if="node.type === 'temporaryGroup' || node.type === 'group' || node.lock"
      class="lock text-primary"
      :name="node.lock ? 'lock_outlined' : 'lock_open_outlined'"
      @click="lockChange"
    ></q-icon>
    <slot></slot>
  </div>
</template>
<style scoped lang="scss">
.node {
  //更换光标
  border: 1px dashed transparent;
  position: absolute;
  top: 0;
  left: 0;
  cursor: grab;
  &:active {
    cursor: grabbing;
  }
  z-index: 999;
  .rotate {
    position: absolute;
    width: 24px;
    height: 24px;
    font-size: 24px;
    top: -28px;
    left: 50%;
    transform: translateX(-50%);
    cursor: grab;
    &:active {
      cursor: grabbing;
    }
  }
  .lock {
    position: absolute;
    width: 24px;
    height: 24px;
    font-size: 24px;
    top: -28px;
    right: 0;
    cursor: pointer;
    display: block;
  }
}
// // 定义resizes
$resizes: (n-resize, s-resize, e-resize, w-resize, ne-resize, se-resize, sw-resize, nw-resize);
// // 遍历resizes
@each $res in $resizes {
  .#{$res} {
    position: absolute;
    width: 8px;
    height: 8px;
    background: $primary;
    border: 1px solid $primary;
    border-radius: 50%;
    z-index: 1;
  }
  .node.#{$res}:hover {
    border: 1px dashed $primary;
  }
}
.active_node {
  border-color: $primary;
}
.lock-node {
  border-color: #ccc;
  border-style: solid;
}
</style>
